home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 2: CDPD 1
/
Almathera Ten on Ten - Disc 2: CDPD 1.iso
/
pd
/
076-100
/
093
/
dme
/
keyboard.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-13
|
13KB
|
568 lines
/*
* KEYBOARD.C
*
* (C)Copyright 1987 by Matthew Dillon
*
* Handle keyboard related stuff such as keyboard mappings. Every time
* a key is pressed, KEYCTL() is called with the code. KEYCTL() remembers
* which qualifier keys are currently held down, and when a non-qualifier
* key is pressed finds the hash entry for the key. If no hash entry
* exists (e.g. you type a normal 'a') the default keymap is used.
*/
#include "defs.h"
typedef struct IOStdReq CIO;
#define QUAL_SHIFT 0x01
#define QUAL_CTRL 0x02
#define QUAL_AMIGA 0x04
#define QUAL_ALT 0x08
#define QUAL_LMB 0x10
#define QUAL_MMB 0x20
#define QUAL_RMB 0x40
#define XBITSET(array,bit) (array[(bit)>>3] |= 1<<((bit)&7))
#define XBITTEST(array,bit) (array[(bit)>>3] & 1<<((bit)&7))
#define HASHSIZE 64
typedef struct _HASH {
struct _HASH *next; /* next hash */
u_char code; /* keycode */
u_char mask; /* qual. mask */
u_char qual; /* qual. comp */
u_char stat; /* string static? */
char *str; /* command string */
} HASH;
HASH *Hash[HASHSIZE];
static u_char isascii[0x80/8]; /* is printable ascii */
static u_char isalpha[0x80/8]; /* is alpha a-z/A-Z */
static u_char ctoa[0x80]; /* cvt to character */
static u_char cstoa[0x80]; /* cvt to shifted chacter */
dealloc_hash()
{
register HASH *hash, *hnext = NULL;
register short i;
for (i = 0; i < HASHSIZE; ++i) {
for (hash = Hash[i]; hash; hash = hnext) {
hnext = hash->next;
if (!hash->stat)
FreeMem(hash->str, strlen(hash->str)+1);
FreeMem(hash, sizeof(HASH));
}
Hash[i] = NULL;
}
}
resethash()
{
register short i;
static struct {
char *from, *to;
} defmap[] = {
"esc", "esc",
"return", "return insline up firstnb down",
"enter", "return",
"up", "up",
"down", "down",
"right", "right",
"left", "left",
"bs", "bs",
"del", "del",
"help", "newwindow newfile s:DME.DOC escimm `find '",
"tab", "tab",
"s-up", "top",
"s-down", "bottom",
"s-right", "last",
"s-left", "first",
"s-tab", "backtab",
"s-del", "deline",
"s- ", "` '", /* shift space to space */
"c-l", "wleft",
"c-r", "wright",
"c-i", "insertmode on",
"c-o", "insertmode off",
"c-j", "join",
"c-s", "split first down",
"c-del", "remeol",
"c-n", "next",
"c-p", "prev",
"c-/", "escimm `find '",
"c-g", "escimm `goto '",
"c-up", "pageup",
"c-down", "pagedown",
"c-q", "quit",
"c-f", "reformat",
"c-w", "wordwrap toggle",
"f1", "escimm `insfile '",
"f2", "escimm `newfile '",
"f3", "escimm `newwindow newfile '",
"f7", "escimm `bsave '",
"f8", "saveold escimm `newfile '",
"f9", "saveold",
"f10", "saveold quit",
"c-b", "block",
"c-u", "unblock",
"a-d", "bdelete",
"a-c", "bcopy",
"a-m", "bmove",
"a-s", "bsource",
"a-S", "unblock block block bsource",
"L-lmb", "tomouse", /* left button */
"L-mmo", "tomouse", /* mouse move w/left held down */
"R-rmb", "iconify", /* right button */
NULL, NULL
};
dealloc_hash();
loaddefaultkeymap();
for (i = 0; defmap[i].from; ++i) {
u_char code, qual;
if (get_codequal(defmap[i].from, &code, &qual))
addhash(code, 1, 0xFF, qual, defmap[i].to);
}
}
/*
* Go through keycodes $00 to $4F and load the ctoa[], cstoa[], and
* isalpha[] char tables from the default console keymap.
*/
loaddefaultkeymap()
{
CIO cio;
struct KeyMap km;
/*
* Note: -1 specification for unit # means that we are not openning
* a real console. We can only execute a CD_ASKDEFAULTKEYMAP through
* it.
*/
if (!OpenDevice("console.device", -1, &cio, 0)) {
cio.io_Command = CD_ASKDEFAULTKEYMAP;
cio.io_Data = (APTR)&km;
cio.io_Length = sizeof(km);
DoIO(&cio);
loadhilo(km.km_LoKeyMapTypes, km.km_LoKeyMap, km.km_LoCapsable, 0, 0x40, 0x00);
loadhilo(km.km_HiKeyMapTypes, km.km_HiKeyMap, km.km_HiCapsable, 0, 0x10, 0x40);
CloseDevice(&cio);
} else {
if (Output())
puts ("Unable to get console keymap");
}
}
/*
* Decode plain and shifted keys only. Ignore strings larger than
* a single character (thus things like the cursor keys do not get
* mapped)
*/
loadhilo(types, map, caps, is, ie, ia)
u_char *types;
u_char *caps;
long *map;
{
register long n;
register int idx;
register u_char *ptr;
u_char c;
for (; is < ie; ++is) {
n = map[is];
if (n && (types[is] & 0x60)) { /* STRING 0x40 or BUG 0x20 */
ptr = (u_char *)n;
n = 0;
if (ptr[0] == 0)
n = ptr[1];
if (ptr[0] == 1)
n = ptr[ptr[1]];
if (types[is] & KCF_SHIFT) {
if (ptr[2] == 0)
n |= ptr[3] << 8;
if (ptr[2] == 1)
n |= ptr[ptr[3]] << 8;
}
}
idx = is + ia;
c = n;
ctoa[idx] = c;
cstoa[idx] = (n>>8) & 0xFF;
if (caps[is>>3] & (1 << (is&7)))
XBITSET(isalpha,idx);
if (c >= 32 && c != 0x7F && ctoa[idx])
XBITSET(isascii,idx);
}
}
returnoveride(n)
{
HASH *hash;
static u_char *str;
static int stat;
for (hash = Hash[0x44 % HASHSIZE]; hash; hash = hash->next) {
if (hash->code == 0x44 && hash->qual == 0) {
if (n) {
str = (u_char *)hash->str;
stat= hash->stat;
hash->str = "return";
hash->stat = 1;
} else {
if (str == NULL) {
remhash(0x44, -1, 0);
} else {
hash->str = (char *)str;
hash->stat= stat;
}
}
return(0);
}
}
if (n) {
addhash(0x44, 1, 0xFF, 0, "return");
str = NULL;
}
}
addhash(code, stat, mask, qual, str)
u_char code, stat, mask, qual;
u_char *str;
{
register HASH **p, *hash;
hash = *(p = &Hash[code % HASHSIZE]);
while (hash) {
if (hash->code == code && hash->qual == qual && hash->mask == mask) {
if (!hash->stat)
FreeMem(hash->str, strlen(hash->str)+1);
goto newstr;
}
hash = *(p = &hash->next);
}
*p = hash = (HASH *)AllocMem(sizeof(HASH), 0);
hash->next = NULL;
newstr:
hash->code = code;
hash->stat = stat;
hash->mask = mask;
hash->qual = qual;
hash->str = (char *)str;
if (!stat) /* if not static */
hash->str = (char *)strcpy(AllocMem(strlen(str)+1, 0), str);
}
remhash(code, mask, qual)
u_char code, mask, qual;
{
register HASH *hash, **p;
hash = *(p = &Hash[code % HASHSIZE]);
while (hash) {
if (hash->code == code && hash->qual == qual && hash->mask == mask) {
if (!hash->stat)
FreeMem(hash->str, strlen(hash->str)+1);
*p = hash->next;
FreeMem(hash, sizeof(HASH));
return(1);
}
hash = *(p = &hash->next);
}
return(0);
}
keyctl(code, qual)
register USHORT qual;
{
register u_char c, c2;
register HASH *hash;
code &= 0xFF;
if ((code & 0x78) == 0x60) /* forget qualifier keys */
return(0);
if (code & 0x80) /* forget upstrokes */
return(0);
c2 = 0;
if (qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
c2 |= QUAL_SHIFT;
if (qual & (IEQUALIFIER_CONTROL))
c2 |= QUAL_CTRL;
if (qual & (IEQUALIFIER_LCOMMAND|IEQUALIFIER_RCOMMAND))
c2 |= QUAL_AMIGA;
if (qual & (IEQUALIFIER_LALT|IEQUALIFIER_RALT))
c2 |= QUAL_ALT;
if ((qual & IEQUALIFIER_CAPSLOCK) && (code <= 0x37) && XBITTEST(isalpha,code))
c2 |= QUAL_SHIFT;
if (qual & IEQUALIFIER_LEFTBUTTON)
c2 |= QUAL_LMB;
if (qual & IEQUALIFIER_MIDBUTTON)
c2 |= QUAL_MMB;
if (qual & (IEQUALIFIER_RBUTTON))
c2 |= QUAL_RMB;
for (hash = Hash[code % HASHSIZE]; hash; hash = hash->next) {
if (hash->code == code) {
if ((c2 & hash->mask) == hash->qual)
break;
}
}
/*
* Use hash entry only if not in command line mode, or if the
* entry does not correspond to an alpha key.
*/
if (hash) {
char buf[256];
/*printf ("c2 %lx BIT: %lx\n", c2, XBITTEST(isascii,code));*/
if (c2 || !ComLineMode || !XBITTEST(isascii,code)) {
strcpy(buf, hash->str);
do_command(buf);
return(0);
}
}
if (code < 0x50) {
c = (c2 & QUAL_SHIFT) ? cstoa[code] : ctoa[code];
if (c2 & QUAL_CTRL)
c &= 0x1F;
if (c && (c2 & QUAL_ALT))
c |= 0x80;
if (c && (c2 & QUAL_AMIGA))
c |= 0xC0;
if (c) {
u_char buf[3];
buf[0] = '\'';
buf[1] = c;
buf[2] = 0;
do_command(buf);
}
}
}
#define LN(a,b,c,d) ((a<<24)|(b<<16)|(c<<8)|d)
long lname[] = {
LN('e','s','c',0x45), LN('f','1', 0 ,0x50), LN('f','2', 0 ,0x51),
LN('f','3', 0 ,0x52), LN('f','4', 0 ,0x53), LN('f','5', 0 ,0x54),
LN('f','6', 0 ,0x55), LN('f','7', 0 ,0x56), LN('f','8', 0 ,0x57),
LN('f','9', 0 ,0x58), LN('f','1','0',0x59), LN('d','e','l',0x46),
LN('b','a','c',0x41), LN('b','s', 0 ,0x41), LN('t','a','b',0x42),
LN('h','e','l',0x5F), LN('r','e','t',0x44), LN('u','p', 0 ,0x4C),
LN('d','o','w',0x4D), LN('r','i','g',0x4E), LN('l','e','f',0x4F),
LN('e','n','t',0x43), LN('n','k','-',0x4A), LN('n','k','.',0x3C),
LN('n','k','0',0x0F),
LN('n','k','1',0x1D), LN('n','k','2',0x1E), LN('n','k','3',0x1F),
LN('n','k','4',0x2D), LN('n','k','5',0x2E), LN('n','k','6',0x2F),
LN('n','k','7',0x3D), LN('n','k','8',0x3E), LN('n','k','9',0x3F),
LN('l','m','b',0x68), LN('m','m','b',0x6A), LN('r','m','b',0x69),
LN('m','m','o',QMOVE),
0
};
char *
keyspectomacro(str)
char *str;
{
HASH *hash;
u_char code, qual;
if (get_codequal(str, &code, &qual)) {
for (hash = Hash[code % HASHSIZE]; hash; hash = hash->next) {
if (hash->code == code) {
if (hash->qual == (qual & hash->mask))
return(hash->str);
}
}
}
title ("Bad command or unmapped key");
return(NULL);
}
get_codequal(str, pcode, pqual)
u_char *pcode, *pqual;
u_char *str;
{
u_char qual;
register short i;
qual = 0;
if (strlen(str) > 1) {
for (; *str && *str != '-'; ++str) {
if (*str == 's')
qual |= QUAL_SHIFT;
if (*str == 'c')
qual |= QUAL_CTRL;
if (*str == 'a')
qual |= QUAL_ALT;
if (*str == 'A')
qual |= QUAL_AMIGA;
if (*str == 'L')
qual |= QUAL_LMB;
if (*str == 'M')
qual |= QUAL_MMB;
if (*str == 'R')
qual |= QUAL_RMB;
if (!qual)
goto notqual;
}
if (*str)
++str;
}
notqual:
*pqual = qual;
if (strlen(str) != 1) { /* long name */
register short shift = 24;
register long mult = 0;
while (*str && shift >= 8) {
if (*str >= 'A' && *str <= 'Z')
*str = *str - 'A' + 'a';
mult |= *str << shift;
shift -= 8;
++str;
}
for (i = 0; lname[i]; ++i) {
if (mult == (lname[i] & 0xFFFFFF00)) {
*pcode = lname[i] & 0x7F;
return(1);
}
}
} else { /* short name */
for (i = 0; i < sizeof(ctoa); ++i) {
if (*str == ctoa[i]) {
*pcode = i;
return(1);
}
}
for (i = 0; i < sizeof(cstoa); ++i) {
if (*str == cstoa[i]) {
*pcode = i;
*pqual |= QUAL_SHIFT;
return(1);
}
}
}
return(0);
}
u_char *
cqtoa(code, qual)
{
static u_char buf[32];
register u_char *ptr = buf;
register int i;
if (qual & QUAL_SHIFT)
*ptr++ = 's';
if (qual & QUAL_CTRL)
*ptr++ = 'c';
if (qual & QUAL_ALT)
*ptr++ = 'a';
if (qual & QUAL_AMIGA)
*ptr++ = 'A';
if (qual & QUAL_LMB)
*ptr++ = 'L';
if (qual & QUAL_MMB)
*ptr++ = 'M';
if (qual & QUAL_RMB)
*ptr++ = 'R';
if (qual)
*ptr++ = '-';
for (i = 0; i < sizeof(lname)/sizeof(lname[0]); ++i) {
if ((lname[i]&0xFF) == code) {
*ptr++ = (lname[i]>>24);
*ptr++ = (lname[i]>>16);
*ptr++ = (lname[i]>>8);
break;
}
}
if (i == sizeof(lname)/sizeof(lname[0]))
*ptr++ = ctoa[code];
*ptr++ = 0;
return(buf);
}
do_map()
{
u_char code, qual;
if (get_codequal(av[1], &code, &qual)) {
addhash(code, 0, 0xFF, qual, av[2]);
} else {
title("Unknown Key");
}
}
do_unmap() /* key */
{
u_char code, qual;
if (get_codequal(av[1], &code, &qual)) {
remhash(code, -1, qual);
} else {
title("Unknown Command");
}
}
do_clearmap()
{
resethash();
}
/*
* SAVEMAP file
* SAVESMAP file
*/
do_savemap()
{
char sysalso;
char err = 0;
u_char buf[256];
long fi;
register int i;
register HASH *hash;
fi = xopen(av[1], "w", 512);
if (fi) {
sysalso = av[0][4] == 's';
for (i = 0; i < HASHSIZE; ++i) {
for (hash = Hash[i]; hash; hash = hash->next) {
if (hash->stat == 0 || sysalso) {
sprintf(buf, "map `%s' `%s'", cqtoa(hash->code, hash->qual), hash->str);
xputs(fi, buf);
}
}
}
xclose(fi);
if (err)
title ("Unable to Write");
else
title ("OK");
} else {
title("Unable to open file");
}
}